//인자들만 객체의 특징을 알기 어렵다.
BigInteger bi = new BigInteger(5, new Random());
//메소드이름을 통하여 자신이 리턴하는 객체의 특징을 설명할 수 있다.
BigInteger bi = BigInteger.probablePrime(5, new Random());
static Employee create(int type){
switch(type){
case ENGINEER :
return create("Engineer");
case SALESMAN :
return create("Salesman");
case MANAGER :
return create("Manager");
default :
throw new IllegalArgumentException("Incorrect type code value");
}
}
//Class.forName을 사용한다.
static Employee create(String name){
try{
return (Employee)Class.forName(name).newInstance();
}catch(Exception e)
throw new IllegalArgumentException("Incorrect type code value");
}
}
//client code..
Employee emp = Employee.create("Engineer");
//SCJP 문제를 참고 했습니다. 어떤 값이 출력 될까요?
public static void main(String[] args) {
String s = "Hello";
String t = " " + "there";
s.concat( t );
s.toLowerCase();
s += " my friend";
System.out.println( s );
}
public class Elvis{
public static final Elvis INSTANCE = new Elvis();
//생성자는 private로 정의 한다.
private Elvis(){
}
//이하 생략
}
//Elvis.INSTANCE로 객체를 사용.
public class Elvis{
private static final Elvis INSTANCE = new Elvis();
private Elvis(){
}
//스태틱 메소드 사용
public static Elvis getInstance(){
return INSTANCE;
}
//이하 생략
}
//Elvis.getInstance로 객체를 사용
public class UtilityClass{
//private생성자를 추가해서 컴파일러에서 자동으로 생성자를 추가하지 못하게 한다.
private UtilityClass(){
}
}
//호출 될 때마다 새로운 인스턴스를 생성한다.
String s = new String("바보"); //오! 제발, 절대 이렇게 하지 말 것!
//매번 새로운 인스턴스를 생성하지 않는다.
String s = "이젠 바보 아니야"; //이렇게 사용해라
| 개선 전 | 개선 후 |
|---|---|
| {code} public class Person{ private final Data birthDate; |
public Person(Date birthDate){
this.birthDate = birthDate;
}
public boolean isBabyBoomer(){
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = gmtCal.getTime();
gmtCal.set(1956, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
return birthDate.compareTo(BOOM_START >= 0 &&
birthDate.compareTo(BOOM_END) < 0;
}
}
|
class Person{
private final Data birthDate;
public Person(Date birthDate){
this.birthDate = birthDate;
}
//베이비 붐의 시작 및 종료 일자
private static final Date BOOM_START;
private static final Date BOOM_END;
static{
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = gmtCal.getTime();
gmtCal.set(1956, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
}
public boolean isBabyBoomer(){
return birthDate.compareTo(BOOM_START >= 0 &&
birthDate.compareTo(BOOM_END) < 0;
}
}
|
h2. 2.5 쓸모없는 객체 참조는 제거하라
* 메모리 누수 위험을 사전에 방지해야 한다.
* 자바에서 메모리 누수란 가비지컬렉션 되어야 하는데도 그 대상이 되지 못하는 객체들이 생기는 경우를 말한다.
* 가비지 컬렉터가 있는 언어에서 메모리 누수 현상은 매우 위험하다.
||개선 전||개선 후||
|
// 어디서 "메모리가 새는지(memory leak)" 찾을 수 있겠는가?
public class Stack{
private object[] elements;
private int size=0;
public Stact(int initialCapacity){
tiis.elements = new Object[initialCapacity];
}
public volid push(Object e){
ensureCapacity();
elements[size++];
}
public Ojbect pop(){
if(size == 0){
throw new EmptyStackException();
return elements[--size];
}
/* 최소한 하나의 구성요소를 담을 수 있는 여유를 두어야 하며
|
public Object pop(){
if(size == 0){
throw new EmptyStackException();
Object result = elements[--size];
element[size] = null; // 쓸모 없는 참조를 없앤다.
return result;
}
|
* Stack클래스의 elements배열과 같이 임시로 다른 객체에 대한 참조를 보관하는 멤버 필드가 있으면 메모리 누수에 대해 항상 생각해야 한다.
h3. 참고2. WeakHashMap
* WeakHashMap 은 HashMap 과 거의 동일하다.
* 다른점은 Map 에서 key 로 접근할 수 없는 Entry 는 자동으로 삭제 한다.
* 즉 시간이 지나면 Garbage Collector 가 WeakHashMap 에서 null 값인 키와 그에 해당하는 값을 제거한다.
* 하지만 HashTable 은 그렇지 않고 그 값을 그대로 유지한다.
h3. 참고3. 가비지 컬렉션
* 자바의 모든 배열과 객체들은 힙(heap) 이라는 메모리 공간에 저장된다.
* new 키워드를 쓸 때마다 힙에 새로운 메모리가 객체마다 활당된다.
* 자바는 C++과 같이 메모리를 반환하는 방법이 없고, 가비지 컬렉터(Garbage Colle:GC)가 사용하지 않는 메모리를 자동으로 수거하는 기능을 한다.
* 참고 URL
** http://j2eestudy.co.kr/lecture/lecture_read.jsp?db=lecture0401_1&table=j2ee&id=1
** http://standcode.com.ne.kr/java/gc/Garbage.ppt
** http://blog.naver.com/dorabn?Redirect=Log&logNo=40047675209
h2. 2.6 종료자(finalizer)들을 쓰지 마라
h4. 2.6.1 종료자란?
* Object 클래스에는 protected 메소드인 finalize 메소드가 있는데 이 객체는 자바의 모든 클래스에서 재정의 할 수 있다.
* 특정 객체에서 실제로 호출되는 finalize 메소드를 이 객체의 종료자라 한다
h4. 2.6.2 finalize의 실행 시점
* 가비지콜렉터가 실행 될 때 자원을 해제하기 전에 finalize 메소드를 호출 한다. 즉 인스턴스가 사라지기 전에 마지막으로 실행된다.
* finalize 메소드는 GC가 해당 인스턴스를 가비지로 판단해서 삭제하기 전 실행되기 때문에.
특정한 인스턴스에 참조가 없다고 하더라도, 언제 GC에 수집될지 전혀 모른다.
즉 finalize메소드에 일반적인 코드가 있으면 언제 실행될지 모른다.
h4. 2.6.3 종료자의 올바른 사용법
* 객체가 소멸되기전에 다른자원도 정리해야 한다면, finalize 메소드를 재정의해 사용할 수 있다.
즉 명시적인 종결처리 메소드를 호출하는 것을 잊었을 경우에 대비해 안전망 역할을 할 수 있다.
하지만 이것도한 종료자가 바로 호출되거나, 반드시 호출 된다는 보장은 없다.
//종료자는 직접 상위 클래스의 종료자를 호출해야 한다.
protected void finalize() throws Throwable {
try {
//하위 클래스 종료 처리
close();
} finally {
super.finalize(); //상위 클래스 종료자 호출
}
}
\\
\\
h2. 문서에 대하여
* 이 문서의 내용은 [자바 유창하게 말하기 - Effective Java|http://book.naver.com/bookdb/book_detail.php?bid=130814] 교재를 스터디 하면서 정리한 내용 입니다.
* 최초작성자 : [김정식]
* 최초작성일 : 2008년 2월 18일
* 이 문서는 [오라클클럽|http://www.gurubee.net] [자바 웹개발자 스터디|제3차 자바 웹개발자 스터디] 모임에서 작성하였습니다.
* 이 문서를 다른 블로그나 홈페이지에 퍼가실 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^\^